﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using SVNClean.Properties;

namespace SVNClean.Modules {
    public class OperationLog {
        /// <summary>
        /// Initializes a new instance of the <see cref="OperationLog"/> class.
        /// </summary>
        public OperationLog() {
            DeletedBackupFiles = new List<string>();
            CreatedBackupFiles = new List<string>();
            CleanedActionFiles = new List<string>();
            StartsActionTime = DateTime.Now;
        }

        #region "[rgn] Public Properties "
        public DirectoryInfo RootDirectory { get; set; }
        public int TotalRootFiles { get; set; }
        public int TotalSvnReferences { get; set; }

        private List<string> DeletedBackupFiles { get; set; }
        private List<string> CreatedBackupFiles { get; set; }
        private List<string> CleanedActionFiles { get; set; }

        private DateTime StartsActionTime { get; set; }
        private DateTime DeleteBackupTime { get; set; }
        private DateTime CreateBackupTime { get; set; }
        private DateTime CleanActionsTime { get; set; }
        private DateTime FinishActionTime { get; set; }
        

        private string tagIdnt { get { return "[§]"; } }
        private string tagInit { get { return "   "; } }
        private string tagDone { get { return tagIdnt + "[Done!]"; } }
        #endregion

        /// <summary>
        /// Adds the operation.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="operation">The operation.</param>
        public void AddOperation(string path, Operation operation) {
            switch (operation) {
                case Operation.DeleteBackup:
                    if (DeletedBackupFiles.Count == 0) {
                        DeleteBackupTime = DateTime.Now;
                    }
                    DeletedBackupFiles.Add(path);
                    break;
                case Operation.CreateBackup:
                    if (CreatedBackupFiles.Count == 0) {
                        CreateBackupTime = DateTime.Now;
                    }
                    CreatedBackupFiles.Add(path);
                    break;
                case Operation.CleanDirectory:
                    if (CleanedActionFiles.Count == 0) {
                        CleanActionsTime = DateTime.Now;
                    }
                    CleanedActionFiles.Add(path);
                    break;
            }
        }

        /// <summary>
        /// Adds the operation.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="action">The action.</param>
        public void AddOperation(string path, string action) {
            AddOperation(path, GetOperation(action));
        }

        /// <summary>
        /// Saves the log file.
        /// </summary>
        public void SaveLogFile() {

            FinishActionTime = DateTime.Now;
            var log = new StringBuilder();            

            log.Append(GetHeaderLogFile());
            log.Append(BuildLogContent());
            log.Append(GetFooterLogFile());

            var writer = new StreamWriter(RootDirectory.FullName + Resources.LogFilePath);
            try {
                writer.Write(log.ToString());
                writer.Flush();
            }
            finally { writer.Close(); }
        }

        /// <summary>
        /// Builds the content of the log.
        /// </summary>
        /// <returns></returns>
        public string BuildLogContent() {
            var log = new StringBuilder();
             
            // Beginner Information.
            log.Append(Environment.NewLine);
            log.Append(Environment.NewLine);
            log.Append(tagIdnt + "[Start Clean Actions]");
            log.Append(Environment.NewLine);
            log.Append(tagInit + RootDirectory.FullName);

            // Removing Backup.
            log.Append(Environment.NewLine);
            log.Append(Environment.NewLine);
            log.Append(tagIdnt + "[Deleting Old Backup].");
            if (DeletedBackupFiles.Count > 0) {
                log.Append(GetFileList(DeletedBackupFiles, DeleteBackupTime));
            }
            log.Append(tagDone);

            // Creating Backup.
            log.Append(Environment.NewLine);
            log.Append(Environment.NewLine);
            log.Append(tagIdnt + "[Creating Backup].");
            if (CreatedBackupFiles.Count > 0) {
                log.Append(GetFileList(CreatedBackupFiles, CreateBackupTime));
            }
            log.Append(tagDone);

            // Clean Actions.
            log.Append(Environment.NewLine);
            log.Append(Environment.NewLine);
            log.Append(tagIdnt + "[Cleaning Root Directory].");
            if (CleanedActionFiles.Count > 0) {
                log.Append(GetFileList(CleanedActionFiles, CleanActionsTime));
            }
            log.Append(tagDone);

            // Succefull Clean.
            log.Append(Environment.NewLine);
            log.Append(Environment.NewLine);
            log.Append(tagDone + "["+ FinishActionTime.ToLongDateString());
            log.Append(" " + FinishActionTime.ToLongTimeString() + "]");
            log.Append(Environment.NewLine);
            log.Append(Environment.NewLine);
            return log.ToString();
        }

        /// <summary>
        /// Gets the header log file.
        /// </summary>
        /// <returns></returns>
        public string GetHeaderLogFile() {
            using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Resources.LogHeaderTemplateFile)) {
                if (resourceStream == null) { throw new Exception(Resources.LogHeaderTemplateFile + " Not Found!"); }
                var reader = new StreamReader(resourceStream, Encoding.GetEncoding(1252));

                var contents = "";
                try { contents = reader.ReadToEnd(); }
                finally { reader.Close(); }



                return string.Format(contents,
                    Assembly.GetExecutingAssembly().GetName().Version.FillLeftSpaces(14),
                    DateTime.Now.ToString("dd/MM/yyyy"),
                    TotalRootFiles.FillLeftZeros(5),
                    TotalSvnReferences.FillLeftZeros(5));
            }
        }

        /// <summary>
        /// Gets the footer log file.
        /// </summary>
        /// <returns></returns>
        public string GetFooterLogFile() {
            using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Resources.LogFooterTemplateFile)) {
                if (resourceStream == null) { throw new Exception(Resources.LogFooterTemplateFile + " Not Found!"); }
                var reader = new StreamReader(resourceStream, Encoding.GetEncoding(1252));

                var contents = "";
                try { contents = reader.ReadToEnd(); }
                finally { reader.Close(); }

                int totalBackuped = 0;
                if (CreatedBackupFiles.Count > 0) { totalBackuped = TotalRootFiles; }

                return string.Format(contents, 
                    Resources.SupportURL,
                    DateTime.Now.Subtract(StartsActionTime).ToString(),
                    totalBackuped.FillLeftZeros(5),
                    CleanedActionFiles.Count.FillLeftZeros(5),
                    DeletedBackupFiles.Count.FillLeftZeros(5),
                    (DeletedBackupFiles.Count + CleanedActionFiles.Count).FillLeftZeros(5)
                    );
            }
        }

        /// <summary>
        /// Gets the file list.
        /// </summary>
        /// <param name="files">The files.</param>
        /// <param name="startDate">The start date.</param>
        /// <returns></returns>
        public string GetFileList(List<string> files, DateTime startDate) {
            var content = new StringBuilder();
            content.Append("[" + startDate.ToLongDateString());
            content.Append(" " + startDate.ToLongTimeString() + "]");

            content.Append(Environment.NewLine);
            //content.Append("{");
            //content.Append(Environment.NewLine);

            foreach (var dir in files) {
                content.Append(tagInit + dir + ";");
                content.Append(" Done.");
                content.Append(Environment.NewLine);
            }
            //content.Append("}");
            //content.Append(Environment.NewLine);
            return content.ToString();
        }

        /// <summary>
        /// Gets the operation.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns></returns>
        public static Operation GetOperation(string action) {
            if (action.ToLower() == Resources.CreatingBackup.ToLower()) {
                return Operation.CreateBackup;
            }
            if (action.ToLower() == Resources.DeleteBackup.ToLower()) {
                return Operation.DeleteBackup;
            }
            if (action.ToLower() == Resources.Cleaning.ToLower()) {
                return Operation.CleanDirectory;
            }
            return Operation.None;
        }
    }
}
